/*
 * ./src/trie_commandes.c
 * Copyright (C) 2009 alexises
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "trie_commandes.h"
#include "fonction_connection.h"
#include "aide.h"
trie_commandes_t *init_commandes(char token, int* nb_commandes)
{
	int nb_cmd = 21;
	*nb_commandes = nb_cmd;
	trie_commandes_t *commandes = malloc(sizeof(trie_commandes_t) * nb_cmd);
	if (commandes == NULL)
	{
		printf("ERREUR : imposible d'alouer de la mémoire pour les commandes\n");
		exit(EXIT_FAILURE);
	}
	else
	{
		memset(commandes, 0, sizeof(trie_commandes_t) * nb_cmd);
		printf("taille commande %d\n", sizeof(trie_commandes_t));
		ajouter_commande(&commandes[0], "dit", cmd_dit, token, SHORT_dit, LONG_dit);
		ajouter_commande(&commandes[1], "debut_inscription", cmd_debut_inscription, token, SHORT_debut_inscription, LONG_debut_inscription);
		ajouter_commande(&commandes[2], "inscription", cmd_inscription, token, SHORT_inscription, LONG_inscription);
		ajouter_commande(&commandes[3], "debut_jeux", cmd_debut_jeux, token, SHORT_debut_jeux, LONG_debut_jeux);
		ajouter_commande(&commandes[4], "definir_leader", cmd_definir_leader, token, SHORT_definir_leader, LONG_definir_leader);
		ajouter_commande(&commandes[5], "passer", cmd_passer, token, SHORT_passer, LONG_passer);
		ajouter_commande(&commandes[6], "ok", cmd_ok, token, SHORT_ok, LONG_ok);
		ajouter_commande(&commandes[7], "stop", cmd_stop, token, SHORT_stop, LONG_stop);
		ajouter_commande(&commandes[8], "kickban", cmd_kickban, token, SHORT_kickban, LONG_kickban);
		ajouter_commande(&commandes[9], "kick", cmd_kick, token, SHORT_kick, LONG_kick);
		ajouter_commande(&commandes[10], "ajouter", cmd_ajouter, token, SHORT_ajouter, LONG_ajouter);
		ajouter_commande(&commandes[11], "retirer", cmd_retirer, token, SHORT_retirer, LONG_retirer);
		ajouter_commande(&commandes[12], "password", cmd_password, token, SHORT_password, LONG_password);
		ajouter_commande(&commandes[13], "sha1sum", cmd_sha1sum, token, SHORT_sha1sum, LONG_sha1sum);
		ajouter_commande(&commandes[14], "score", cmd_score, token, SHORT_score, LONG_score);
		ajouter_commande(&commandes[15], "ajouter_cat", cmd_ajouter_cat, token, SHORT_ajouter_cat, LONG_ajouter_cat);
		ajouter_commande(&commandes[16], "retirer_cat", cmd_retirer_cat, token, SHORT_retirer_cat, LONG_retirer_cat);
		ajouter_commande(&commandes[17], "changer_cat", cmd_changer_cat, token, SHORT_changer_cat, LONG_changer_cat);
		ajouter_commande(&commandes[18], "score_total", cmd_score_total, token, SHORT_score_total, LONG_score_total);
		ajouter_commande(&commandes[19], "hlme", cmd_hlme, token, SHORT_hlme, LONG_hlme);
		ajouter_commande(&commandes[20], "aide", cmd_aide, token, SHORT_aide, LONG_aide);
		//trie du tableau
		qsort(commandes, nb_cmd, sizeof(trie_commandes_t), qsort_compare);
		return commandes;
	}
}

void ajouter_commande(trie_commandes_t * commandes, char *nom_commande,
		      void (*callback) (donnee_de_control *, const char *, irc_session_t *, const char **, size_t), char token, char *short_desc,
		      char *long_desc)
{
	commandes->nom_commande = (char *) g_strdup_printf("%c%s", token, nom_commande);
	commandes->callback = callback;
	commandes->taille_cmd = strlen(commandes->nom_commande);
	commandes->short_desc = (char *) g_strdup_printf("%s", short_desc);
	commandes->long_desc = (char *) g_strdup_printf("%s", long_desc);
}

int qsort_compare(const void *case1, const void *case2)
{
	return strcmp(((trie_commandes_t *) case1)->nom_commande, ((trie_commandes_t *) case2)->nom_commande);
}

trie_commandes_t *rechercher_commandes(const char *nom, trie_commandes_t * cmd, int nb_cmd)
{
	int haut = nb_cmd - 1;
	int bas = 0;
	int milieux = -1;

	while (bas <= haut)
	{
		milieux = (bas + haut) / 2;
		int resultat = strncmp(nom, cmd[milieux].nom_commande, cmd[milieux].taille_cmd);

		if (resultat == 0)
		{
			printf("DEBUG : return\n");
			return &cmd[milieux];
		}
		else if (resultat > 0)
		{
			printf("DEBUG interval du haut\n");
			bas = milieux + 1;
		}
		else if (resultat < 0)
		{
			printf("DEBUG interval du bas\n");
			haut = milieux - 1;
		}
		printf("DEBUG : [%d;%d]\n", bas, haut);
		printf("DEBUG : [%s;%s]\n", cmd[bas].nom_commande, cmd[haut].nom_commande);

		if (bas == haut)
		{
			break;
		}
	}
	milieux = (bas + haut) / 2;
	if (!strncmp(nom, cmd[milieux].nom_commande, cmd[milieux].taille_cmd))
	{
		return &cmd[milieux];
	}
	else
	{
		return NULL;
	}
}
